package com.orange.cloud.common.log.aspect;

import com.orange.cloud.common.exception.ServiceException;
import com.orange.cloud.common.log.dtl.CodeMsg;
import com.orange.cloud.common.msg.Message;
import com.google.gson.Gson;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.BeanUtils;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;
import java.math.BigDecimal;

/**
 * @program:
 * @description: 全局日志收集
 * @author: wsw
 * @create: 2020-07-02 15:04
 **/
@Slf4j
@Aspect
@Order(5)
@Component
public class LogAspect {

    private static final String BUFFER = "|#|";

    private static final String INTERVAL = "&";

    /**
     * controller切入点
     */
    @Pointcut("execution(public * com.orange.cloud..*.controllertest..*.*(..))")
    public void webLog() {
    }

    @Around(value = "webLog()")
    public Object aopLog(ProceedingJoinPoint point) {
        //从切面织入点处通过反射机制获取织入点处的方法
        MethodSignature signature = (MethodSignature) point.getSignature();
        //获取切入点所在的方法
        Method method = signature.getMethod();
        //请求的参数
        StringBuffer inParaBuffer = new StringBuffer();
        Object[] args = point.getArgs();
        //将参数所在的数组转换成json
        for (Object obj : args) {
            if (!(obj instanceof HttpServletRequest) && !(obj instanceof HttpServletResponse)) {
            }
        }
        if (inParaBuffer.toString().contains(INTERVAL)) {
            inParaBuffer.delete(inParaBuffer.lastIndexOf(INTERVAL), inParaBuffer.length());
        }
        //接收到请求，记录请求内容
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();

        //IP
        String remoteIp = this.getRemoteHost(request);
        //token
        String token = this.getToken(request);

        //拼接参数
        Integer respCode = -999999999;
        String respMsg = "";
        String outMessage = "";
        String apiName = "";
        String accountId = "";
        String accountNum = "";
        String accountType = "";
        String userId = "";
        String userName = "";
        String userSrc = "";

        try{
            //从swagger的注解上取名称
            ApiOperation apiOperation = method.getAnnotation(ApiOperation.class);
            if (apiOperation != null) {
                apiName = apiOperation.value();
            }

        }catch(Exception e) {
            log.error(e.getMessage(),e);
        }
        Object result;
        //开始调用时间
        long start = System.currentTimeMillis();
        try {
            result = point.proceed();
            long end = System.currentTimeMillis();
            long time = (end - start);
            if (result != null) {
                if (result instanceof Message) {
                    Message message = new Message();
                    BeanUtils.copyProperties(result, message);
                    respCode = message.getHead().getRespCode();
                    respMsg = message.getHead().getRespMsg();
                    Gson gson = new Gson();
                    outMessage = gson.toJson(message);
                } else {
                    CodeMsg codeMsg = new CodeMsg();
                    BeanUtils.copyProperties(result, codeMsg);
                    if (codeMsg.getCode() != null) {
                        respCode = codeMsg.getCode();
                    }
                    if (StringUtils.isNotEmpty(codeMsg.getMsg())) {
                        respMsg = codeMsg.getMsg();
                    }
                    if(null!=result){
                        outMessage = result.toString();
                    }
                }
            }

            // 记录下请求内容： traceId链路（预留），spanId（预留），IP，token，用户ID，用户姓名，接口名称，接口路径，耗时，响应编码，响应消息，入参，出参，用户类型，账户ID，账号，账号类型
            StringBuffer sb = new StringBuffer(BUFFER);
            //traceId链路（预留）
            sb.append("" + BUFFER);
            //spanId（预留）
            sb.append("" + BUFFER);
            //IP
            sb.append(remoteIp + BUFFER);
            //token
            sb.append(token + BUFFER);
            //用户ID
            sb.append(userId + BUFFER);
            //用户名称
            sb.append(userName + BUFFER);
            //api名称
            sb.append(apiName + BUFFER);
            //api路径
            sb.append(request.getRequestURI() + BUFFER);
            //耗时
            sb.append(time + BUFFER);
            //响应编码
            sb.append(respCode + BUFFER);
            //响应消息
            sb.append(respMsg + BUFFER);
            //入参
            sb.append(inParaBuffer.toString() + BUFFER);
            //出参
            sb.append(outMessage + BUFFER);
            //账户ID
            sb.append(accountId + BUFFER);
            //账号
            sb.append(accountNum + BUFFER);
            //账号类型
            sb.append(accountType + BUFFER);
            //用户类型：PUB|PRI
            sb.append(userSrc + BUFFER);
            sb.append(BUFFER);

            log.info(sb.toString());
            return result;
        } catch (Throwable throwable) {
            throwable.printStackTrace();
            throw new ServiceException(500,throwable.getMessage());
        }
    }

    private void checkType(Object obj, StringBuffer buffer) {
        Class<?> clazz = obj.getClass();
        if (clazz == String.class) {
            buffer.append(obj).append(INTERVAL);
        } else if (clazz == Long.class) {
            buffer.append(obj).append(INTERVAL);
        } else if (clazz == Boolean.class) {
            buffer.append(obj).append(INTERVAL);
        } else if (clazz == Byte.class) {
            buffer.append(obj).append(INTERVAL);
        } else if (clazz == Integer.class) {
            buffer.append(obj).append(INTERVAL);
        } else if (clazz == Double.class) {
            buffer.append(obj).append(INTERVAL);
        } else if (clazz == BigDecimal.class) {
            buffer.append(obj).append(INTERVAL);
        } else if (clazz == Short.class) {
            buffer.append(obj).append(INTERVAL);
        } else if (clazz == Float.class) {
            buffer.append(obj).append(INTERVAL);
        } else if (obj instanceof MultipartFile) {
            buffer.append("file").append(INTERVAL);
        } else {
            Gson gson = new Gson();
            String s = gson.toJson(obj);
            buffer.append(s);
        }
    }


    private String getRemoteHost(HttpServletRequest request){
        String ip = request.getHeader("x-forwarded-for");

        if(ip!=null&&ip.length()>0&&!"unknown".equalsIgnoreCase(ip)){
            ip = ip.split(",")[0];
        }
        if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)){
            ip = request.getHeader("Proxy-Client-IP");
        }
        if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)){
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)){
            ip = request.getRemoteAddr();
        }
        return "0:0:0:0:0:0:0:1".equals(ip)?"127.0.0.1":ip;
    }

    private String getToken(HttpServletRequest request){
        return null==request.getHeader("Authorization")?"":request.getHeader("Authorization");
    }


}
